<?php
/**
 * Created by Denis S.
 * Date: 03.04.11
 * Time: 15:28
 */
 
class Maze
{
    protected $_height = null;
    protected $_width  = null;

    /**
     * @param int $height
     * @param int $width
     */
    public function __construct($height, $width)
    {
        require_once('cell.php');
        require_once('cellEntity.php');

        $this->_setHeight($height);
        $this->_setWidth($width);
    }

    /**
     * @return string
     */
    public function ajaxGetMaze()
    {
        $mazeHtml = null;
        if (isset($_POST['ajaxGetMaze']) && $_POST['ajaxGetMaze'] != null) {
            $mazeHtml = '<table class="maze">';
            $arrMaze = $this->getMaze();
            foreach ($arrMaze as $tr) {
                $mazeHtml .= '<tr>';
                foreach ($tr as $cell) {
                    $mazeHtml .= '<td class="';
                    if ($cell->getStart()) {
                        $mazeHtml .= ' start';
                    } else if ($cell->getFinish()) {
                        $mazeHtml .= ' finish';
                    }

                    // set up wall class
                    $mazeHtml .= ' upWall-' . $this->_setWallType($cell->getUpWall());
                    // set down wall class
                    $mazeHtml .= ' downWall-' . $this->_setWallType($cell->getDownWall());
                    // set left wall class
                    $mazeHtml .= ' leftWall-' . $this->_setWallType($cell->getLeftWall());
                    // set right wall class
                    $mazeHtml .= ' rightWall-' . $this->_setWallType($cell->getRightWall());

                    $mazeHtml .= '"></td>';
                }
                $mazeHtml .= '</tr>';
            }
            $mazeHtml .= '</table>';
        }

        return $mazeHtml;
    }

    /**
     * @param int $wall
     * @return string
     */
    private function _setWallType($wall)
    {
        $typeWall = '';

        switch ($wall) {
            case cellEntity::EMPTY_WALL: {
                $typeWall = 'empty';
            }
            break;
            case cellEntity::STONE_WALL: {
                $typeWall = 'stone';
            }
            break;
            case cellEntity::EXTREME_WALL: {
                $typeWall = 'extreme';
            }
            break;
            case cellEntity::FINISH_WALL: {
                $typeWall = 'finish';
            }
            break;
            case cellEntity::START_WALL: {
                $typeWall = 'start';
            }
            break;
            default :{
                $typeWall = 'stone';
            }
        }

        return $typeWall;
    }

    /**
     * @return array
     */
    public function getMaze()
    {
        $height = $this->_getHeight();
        $width  = $this->_getWidth();

        $arrStart  = $this->_makeStart($height, $width);
        $arrFinish = $this->_makeFinish($height, $width, $arrStart);

        $arrMaze = $this->_generateMaze($arrStart, $arrFinish, $height, $width);

        return $arrMaze;
    }

    /**
     * @param array $arrStart
     * @param array $arrFinish
     * @param int $height
     * @param int $width
     * @return array
     */
    private function _generateMaze($arrStart, $arrFinish, $height, $width)
    {
        $arrMaze = array();

        for ($x = 0; $x <= $width; $x++) {
            for ($y = 0; $y <= $height; $y++) {
                if (($x == $arrStart[0]) && ($y == $arrStart[1])) {
                    $oCell = new cellEntity($x, $y, true);
                } else if (($x == $arrFinish[0]) && ($y == $arrFinish[1])) {
                    $oCell = new cellEntity($x, $y, false, true);
                } else {
                    $oCell = new cellEntity($x, $y);
                }

                $arrMaze[$x][$y] = $oCell;
            }
        }

        return $arrMaze;
    }

    /**
     * @param int $height
     * @param int $width
     * @return array
     */
    private function _makeStart($height, $width)
    {
        $startX = rand(0, $width);

        if (($startX == 0) || ($startX == $height)) {
            $startY = rand(0, $height);
        } else {
            $arrForStartY = array(0, $width);
            shuffle($arrForStartY);
            $startY = $arrForStartY[0];
        }

        return array($startX, $startY);
    }

    /**
     * @param int $height
     * @param int $width
     * @param array $arrStart
     * @return array
     */
    private function _makeFinish($height, $width, $arrStart)
    {
        $startY = $arrStart[1];
        $startX = $arrStart[0];

        if ($startY == 0) {
            $finishY = $width;
            $finishX = rand(0, $height);
        } else if ($startY == $width) {
            $finishY = 0;
            $finishX = rand(0, $height);
        } else {
            if ($startX == 0) {
                $finishX = $height;
            } else if ($startX == $height) {
                $finishX = 0;
            }

            $finishY = rand(0, $width);
        }

        return array($finishX, $finishY);
    }

    /**
     * @param int $height
     * @return Maze
     */
    private function _setHeight($height)
    {
        $this->_height = $height;

        return $this;
    }

    /**
     * @param int $width
     * @return Maze
     */
    private function _setWidth($width)
    {
        $this->_width = $width;

        return $this;
    }

    /**
     * @return null|int
     */
    private function _getHeight()
    {
        return $this->_height;
    }

    /**
     * @return null|int
     */
    private function _getWidth()
    {
        return $this->_width;
    }
}